package com.ischoolbar.programmer.controller.home;

import com.alibaba.fastjson.JSONObject;
import org.springframework.web.socket.server.standard.SpringConfigurator;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * @author Losca
 * @date 2022/5/2 16:34
 */
//websocket连接URL地址和可被调用配置 @ServerEndpoint这个注解用来标记一个类是 WebSocket 的处理器。
@ServerEndpoint(value="/websocketDemo/{userid}",configurator = SpringConfigurator.class)
public class MessageController {

    //静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;

    //记录每个用户下多个终端的连接
    public static Map<String, Set<MessageController>> userSocket = new HashMap<>();
    //需要session来对用户发送数据, 获取连接特征fromName
    private Session session;
    private String fromName;
    private String toName;

    /**
     * @Title: onOpen
     * @Description: websocekt连接建立时的操作
     * @param @param fromName 用户id
     * @param @param session websocket连接的session属性
     * @param @throws IOException
     */
    @OnOpen
    public void onOpen(@PathParam("userid") String fromName, Session session) throws IOException{
        this.session = session;
        this.fromName = fromName;
        onlineCount++;
        //根据该用户当前是否已经在别的终端登录进行添加操作
        if (userSocket.containsKey(this.fromName)) {
            userSocket.get(this.fromName).add(this); //增加该用户set中的连接实例
        }else {
            Set<MessageController> addUserSet = new HashSet<>();
            addUserSet.add(this);
            userSocket.put(this.fromName, addUserSet);
        }

    }

    /**
     * @Title: onClose
     * @Description: 连接关闭的操作
     */
    @OnClose
    public void onClose(){
        //移除当前用户终端登录的websocket信息,如果该用户的所有终端都下线了，则删除该用户的记录
        if (userSocket.get(this.fromName).size() == 0) {
            userSocket.remove(this.fromName);
        }else{
            userSocket.get(this.fromName).remove(this);
        }
        userSocket.remove(this.fromName);
    }

    /**
     * @Title: onMessage
     * @Description: 收到消息后的操作
     * @param @param message 收到的消息
     * @param @param session 该连接的session属性
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        JSONObject jsonObject = JSONObject.parseObject(message);//将前台转来的字符串转为json对象
        this.toName = jsonObject.getString("toName");

        if(userSocket.containsKey(toName)) {
            sendMessageToUser(toName, message);
        }else {

        }
        if(session ==null) System.out.println("null");
    }

    /**
     * @Title: onError
     * @Description: 连接发生错误时候的操作
     * @param @param session 该连接的session
     * @param @param error 发生的错误
     */
    @OnError
    public void onError(Session session, Throwable error){
        error.printStackTrace();
    }

    /**
     * @Title: sendMessageToUser
     * @Description: 发送消息给用户下的所有终端
     * @param @param fromName 用户id
     * @param @param message 发送的消息
     * @param @return 发送成功返回true，反则返回false
     */
    public Boolean sendMessageToUser(String toName,String message){
        if (userSocket.containsKey(toName)) {
            for (MessageController WS : userSocket.get(toName)) {
                try {
                    WS.session.getBasicRemote().sendText(message);//将消息发送给对方 getBasicRemote().sendText(message) 同步发送
                } catch (IOException e) {
                    e.printStackTrace();
                    return false;
                }
            }
            return true;
        }
        return false;
    }
}